/*
 * map.c
 *
 *  Created on: 15 nov. 2010
 *      Author: Nicolas Aucouturier, Laurent Reveillere, Vincent Filou
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <SDL.h>
#include <SDL_image.h>
/*
#include <time.h>
#include "../include/constant.h"
#include "../include/map.h"
#include "../include/misc.h"
#include "../include/bomb.h"
*/
#include "../include/game.h"
#include "../include/map.h"
#include "../include/player.h"
#include "../include/misc.h"
#include "../include/level.h"
#include "../include/bomb.h"
#include "../include/list_bomb.h"

typedef char t_cell_type_;



struct s_map {
	int width;
	int height;

	t_cell_type_* grid;

	SDL_Surface* img_box;
	SDL_Surface* img_goal;
	SDL_Surface* img_bonus_bomb_range_inc;
	SDL_Surface* img_bonus_bomb_range_dec;
	SDL_Surface* img_bonus_bomb_nb_inc;
	SDL_Surface* img_bonus_bomb_nb_dec;
	SDL_Surface* img_key;
	SDL_Surface* img_door;
	SDL_Surface* img_closed_door;
	SDL_Surface* img_stone;
	SDL_Surface* img_tree;
	SDL_Surface* img_monster_left;
	SDL_Surface* img_monster_up;
	SDL_Surface* img_monster_right;
	SDL_Surface* img_monster_down;


};
/*
	 * SDL_Surface* img_bomb_TTL4;
	SDL_Surface* img_bomb_TTL3;
	SDL_Surface* img_bomb_TTL2;
	SDL_Surface* img_bomb_TTL1;*/

#define CELL(i,j) (i +  map->width * j)

t_map map_new(int width, int height) {
	assert(width > 0 && height > 0);

	t_map map = malloc(sizeof (struct s_map));
	if (map == NULL )
		exit(EXIT_FAILURE);

	map->width = width;
	map->height = height;

	map->grid = (t_cell_type_ *) malloc(height * width * sizeof(t_cell_type_));
	if (map->grid == NULL )
		exit(EXIT_FAILURE);

	// Grid cleaning
	int i, j;
	for (i = 0; i < width; i++) {
		for (j = 0; j < height; j++) {
			map->grid[CELL(i,j)] = CELL_EMPTY;
		}
	}

	// Sprite loading
	map->img_tree =load_image(IMG_MAP_TREE);
	map->img_box = load_image(IMG_MAP_CASE);
	map->img_goal = load_image(IMG_MAP_GOAL);
	map->img_key = load_image(IMG_MAP_KEY);
	map->img_stone = load_image(IMG_MAP_STONE);
	map->img_door = load_image(IMG_MAP_DOOR);
	map->img_closed_door = load_image(IMG_MAP_CLOSED_DOOR);
	map->img_bonus_bomb_range_inc = load_image(IMG_BONUS_BOMB_RANGE_INC);
	map->img_bonus_bomb_range_dec = load_image(IMG_BONUS_BOMB_RANGE_DEC);
	map->img_bonus_bomb_nb_inc = load_image(IMG_BONUS_BOMB_NB_INC);
	map->img_bonus_bomb_nb_dec = load_image(IMG_BONUS_BOMB_NB_DEC);
		map->img_monster_left = load_image(IMG_MONSTER_LEFT);
		map->img_monster_up = load_image(IMG_MONSTER_UP);
		map->img_monster_right = load_image(IMG_MONSTER_RIGHT);
		map->img_monster_down = load_image(IMG_MONSTER_DOWN);

	return map;
}
/*
	map->img_bomb_TTL4= load_image(IMG_BOMB_TTL4); //Add sprite for bomb
	map->img_bomb_TTL3= load_image(IMG_BOMB_TTL3);
	map->img_bomb_TTL2= load_image(IMG_BOMB_TTL2);
	map->img_bomb_TTL1= load_image(IMG_BOMB_TTL1);
	*/

int map_is_inside(t_map map, int x, int y) {
	assert(map != NULL);
		if (x<map_get_width(map) && y<map_get_height(map) && x>=0 && y>=0 )
			return 1;
		return 0;
}

void map_free(t_map map) {
	if (map == NULL ) {
		return;
	}

	free(map->grid);

	SDL_FreeSurface(map->img_bonus_bomb_nb_dec);
	SDL_FreeSurface(map->img_bonus_bomb_nb_inc);
	SDL_FreeSurface(map->img_bonus_bomb_range_dec);
	SDL_FreeSurface(map->img_bonus_bomb_range_inc);
	SDL_FreeSurface(map->img_closed_door);
	SDL_FreeSurface(map->img_door);
	SDL_FreeSurface(map->img_key);
	SDL_FreeSurface(map->img_stone);
	SDL_FreeSurface(map->img_box);
	SDL_FreeSurface(map->img_goal);
	SDL_FreeSurface(map->img_tree);
	/*
	SDL_FreeSurface(map->img_bomb_TTL4);//To free memory from image bomb
	SDL_FreeSurface(map->img_bomb_TTL3);
	SDL_FreeSurface(map->img_bomb_TTL2);
	SDL_FreeSurface(map->img_bomb_TTL1);*/
	// (3) Je permets de libérer les cases des images qui y ont été placées ----------
		SDL_FreeSurface(map->img_monster_left);
		SDL_FreeSurface(map->img_monster_up);
		SDL_FreeSurface(map->img_monster_right);
		SDL_FreeSurface(map->img_monster_down);
		// Fin de (3) ----------

	free(map);
}

int map_get_width(t_map map) {
	assert(map != NULL);
	return map->width;
}

int map_get_height(t_map map) {
	assert(map != NULL);
	return map->height;
}

t_cell_type map_get_cell_type(t_map map, int x, int y) {
	if(!(map && map_is_inside(map, x, y))) {
		return -1;
	}
	return map->grid[CELL(x,y)] & 7;
}

void map_set_cell_type(t_map map, int x, int y, t_cell_type type) {
	assert(map && map_is_inside(map, x, y));
	map->grid[CELL(x,y)] = type;
}



void display_bonus(t_map map, SDL_Surface* screen, SDL_Rect* place,
		t_cell_type_ type) {
	// bonus is encoded with the 4 most significant bits
	switch (type >> 4) {
	case BONUS_BOMB_RANGE_INC:
		SDL_BlitSurface(map->img_bonus_bomb_range_inc, NULL, screen, place);
		break;

	case BONUS_BOMB_RANGE_DEC:
		SDL_BlitSurface(map->img_bonus_bomb_range_dec, NULL, screen, place);
		break;

	case BONUS_BOMB_NB_INC:
		SDL_BlitSurface(map->img_bonus_bomb_nb_inc, NULL, screen, place);
		break;

	case BONUS_BOMB_NB_DEC:
		SDL_BlitSurface(map->img_bonus_bomb_nb_dec, NULL, screen, place);
		break;
	}
}

void display_scenery(t_map map, SDL_Surface* screen, SDL_Rect* place,
		t_cell_type_ type) {

	switch (type >> 4) {
	case SCENERY_STONE:
		SDL_BlitSurface(map->img_stone, NULL, screen, place);
		break;

	case SCENERY_TREE:
		SDL_BlitSurface(map->img_tree, NULL, screen, place);
		break;
	}
}

void map_display(t_map map, SDL_Surface *screen) {
	int i, j;

	assert(map != NULL);
	assert(screen != NULL);
	assert(map->height > 0 && map->width > 0);

	assert(map->img_bonus_bomb_nb_dec != NULL);
	assert(map->img_bonus_bomb_nb_inc != NULL);
	assert(map->img_bonus_bomb_range_dec != NULL);
	assert(map->img_bonus_bomb_range_inc != NULL);
	assert(map->img_closed_door != NULL);
	assert(map->img_door != NULL);
	assert(map->img_key != NULL);
	assert(map->img_stone != NULL);
	assert(map->img_box != NULL);
	assert(map->img_goal != NULL);
	//assert(map->img_bomb_TTL4 != NULL);
	// (4) Je pourrai afficher un monstre grâce à la fonction map_display ----------
	assert(map->img_monster_left != NULL);
	assert(map->img_monster_up != NULL);
	assert(map->img_monster_right != NULL);
	assert(map->img_monster_down != NULL);
	// Fin de (4) ----------

	for (i = 0; i < map->width; i++) {
		for (j = 0; j < map->height; j++) {
			SDL_Rect place;
			place.x = i * SIZE_BLOC;
			place.y = j * SIZE_BLOC;

			t_cell_type_ type = map->grid[CELL(i,j)];

			switch (type & 15) { // type is encoded with 4 bits (the & 15 (1111)) is a mask to keep the four less significant bits)
			case CELL_GOAL:
				SDL_BlitSurface(map->img_goal, NULL, screen, &place);
				break;
			case CELL_SCENERY:
				display_scenery(map, screen, &place, type);
				break;
			case CELL_CASE:
				SDL_BlitSurface(map->img_box, NULL, screen, &place);
				break;
			case CELL_BONUS:
				display_bonus(map, screen, &place, type);
				break;
			case CELL_KEY:
				SDL_BlitSurface(map->img_key, NULL, screen, &place);
				break;
			case CELL_DOOR:
				SDL_BlitSurface(map->img_door, NULL, screen, &place);
				break;
			case CELL_CLOSED_DOOR:
				SDL_BlitSurface(map->img_closed_door, NULL, screen, &place);
				break;
			case CELL_MONSTER_LEFT:
							SDL_BlitSurface(map->img_monster_left, NULL, screen, &place);
							//fprintf(stderr,"voici");
							break;
			case CELL_MONSTER_UP:
				SDL_BlitSurface(map->img_monster_up, NULL, screen, &place);
				//fprintf(stderr,"voici");
				break;
				case CELL_MONSTER_RIGHT:
								SDL_BlitSurface(map->img_monster_right, NULL, screen, &place);
								fprintf(stderr,"voici");
								break;
			case CELL_MONSTER_DOWN:
				SDL_BlitSurface(map->img_monster_down, NULL, screen, &place);
				break;


			default:
				break;

			}
		}

	}
}
/*
void createListe(){

	list newlist = malloc(sizeof(*newlist));

}
*/
t_map map_get_default(void) {
	t_map map = map_new(12, 12);
	t_cell_type_ themap[144] = {
			CELL_PLAYER, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY,
			CELL_STONE, CELL_STONE, CELL_STONE, CELL_EMPTY, CELL_STONE, CELL_EMPTY, CELL_STONE, CELL_STONE, CELL_STONE, CELL_STONE, CELL_EMPTY, CELL_EMPTY,
			CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_STONE, CELL_CASE, CELL_STONE, CELL_EMPTY, CELL_EMPTY, CELL_STONE, CELL_EMPTY, CELL_EMPTY,
			CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_STONE, CELL_CASE, CELL_STONE, CELL_EMPTY, CELL_EMPTY, CELL_STONE, CELL_EMPTY, CELL_EMPTY,
			CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_STONE, CELL_KEY, CELL_STONE, CELL_EMPTY, CELL_EMPTY, CELL_STONE, CELL_EMPTY, CELL_EMPTY,
			CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_STONE, CELL_STONE, CELL_STONE, CELL_EMPTY, CELL_EMPTY, CELL_STONE, CELL_EMPTY, CELL_EMPTY,
			CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY , CELL_EMPTY, CELL_EMPTY, CELL_STONE,  CELL_EMPTY, CELL_EMPTY,
			CELL_EMPTY, CELL_TREE, CELL_CASE, CELL_TREE, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY,  CELL_EMPTY, CELL_STONE,  CELL_EMPTY, CELL_EMPTY,
			CELL_EMPTY, CELL_TREE, CELL_TREE, CELL_TREE, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY,  CELL_STONE,  CELL_EMPTY, CELL_EMPTY,
			CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_STONE,  CELL_EMPTY, CELL_EMPTY,
			CELL_CASE, CELL_STONE, CELL_STONE, CELL_STONE, CELL_STONE, CELL_STONE, CELL_STONE, CELL_STONE, CELL_STONE, CELL_STONE,  CELL_CASE_LIFE, CELL_EMPTY,
			CELL_CLOSED_DOOR,  CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_EMPTY, CELL_DOOR
		};
	for (int i = 0; i < 144; i++) {
		map->grid[i] = themap[i];
	}
	return map;
}
